package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.model.constant.GroupConstants;
import com.alibaba.cirtus.ots.application.adapter.ability.strategy.StrategyQueryAbility;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.InfoUtil;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.RemoveZeroUtil;
import com.alibaba.citrus.cr.common.enums.ordercenter.AsyncMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderPushStatusEnum;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.lock.RedisLock;
import com.alibaba.citrus.ots.common.lock.SaleRedisLock;
import com.alibaba.citrus.ots.common.util.IntegrateUtils;
import com.alibaba.citrus.ots.common.util.JsonUtil;
import com.alibaba.citrus.ots.common.util.SapAndCrmFieldDealUtils;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.contants.BcOtsConstants;
import com.epoch.app.crb2btradecenter.domain.order.dto.LoadOrderListRequest;
import com.epoch.app.crb2btradecenter.domain.order.model.Order;
import com.epoch.app.crb2btradecenter.domain.order.service.OrderService;
import com.epoch.app.crb2btradecenter.domain.orderline.dto.OrderLineLoadListRequest;
import com.epoch.app.crb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.crb2btradecenter.domain.orderline.service.OrderLineService;
import com.epoch.app.crb2btradecenter.model.dto.OrderBackUpLoadListRequest;
import com.epoch.app.crb2btradecenter.model.dto.OrderLineBackUpLoadListRequest;
import com.epoch.app.crb2btradecenter.orderbackup.model.OrderBackUp;
import com.epoch.app.crb2btradecenter.orderbackup.service.OrderBackUpService;
import com.epoch.app.crb2btradecenter.orderlinebackup.model.OrderLineBackUp;
import com.epoch.app.crb2btradecenter.orderlinebackup.service.OrderLineBackUpService;
import com.epoch.app.crunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.crunifiedinventory.api.consignmentorderwrite.service.ConsignmentOrderWriteService;
import com.epoch.app.crunifiedinventory.consignmentorder.model.ConsignmentOrder;
import com.epoch.app.crunifiedinventory.consignmentorder.service.ConsignmentOrderService;
import com.epoch.app.crunifiedinventory.consignmentorderline.model.ConsignmentOrderLine;
import com.epoch.app.crunifiedinventory.consignmentorderline.service.ConsignmentOrderLineService;
import com.epoch.app.crunifiedinventory.model.dto.*;
import com.epoch.app.crunifiedinventory.service.CrUnifiedInventoryService;
import com.epoch.app.mnordercenter.model.dto.CommonAsyncMessageResponse;
import com.epoch.app.mnordercenter.model.dto.PushOrderInfoToMnSideRequestOrderInfo;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetrySaveRequest;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.model.enums.SapApiCode;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommResponse;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommSDO;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf018Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf018SDO;
import com.epoch.app.otsapplicationadaptersdk.sapretrywrite.service.SapRetryWriteService;
import com.epoch.app.otsapplicationadaptersdk.sapv2.mnsapif018v2.service.MnSapIf018V2Service;
import com.epoch.app.otsunifiedinventory.model.dto.WmsSDO;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author
 * @date 2021/10/12
 * @Description sap请求平台同步交货单删除
 */
@Component
@Primary
public class MnSapIf018V2ServiceImpl implements MnSapIf018V2Service {
    private final Log log = Log.getLogger(MnSapIf018V2ServiceImpl.class);

    @Resource
    private ConsignmentOrderWriteService consignmentOrderWriteService;
    @Resource
    private AllocateOrderWriteService allocateOrderWriteService;
    @Resource
    private ConsignmentOrderService consignmentOrderService;
    @Resource
    private SapRetryWriteService sapRetryWriteService;
    @Resource
    private OrderService orderService;
    @Resource
    private ConsignmentOrderLineService consignmentOrderLineService;
    @Resource
    private OrderLineService orderLineService;
    @Resource
    private CrUnifiedInventoryService crUnifiedInventoryService;
    @Resource
    private OrderBackUpService orderBackUpService;
    @Resource
    private OrderLineBackUpService orderLineBackUpService;
    @Resource
    private EpochMessageService messageService;
    @Resource
    private StrategyQueryAbility strategyQueryAbility;
    private static final String DELIVERY_ORDER_LOCK = "DELIVERY_ORDER_LOCK_";
    public static final String SAP_SYNC = "sapSync:";
    private static final String LOCK_PREFIX = "saleLock:";
    private static final String SPEC_ORG = "1171";
    private static final String DELIVERY_ORDER_CACHE_KEY = "DELIVERY_ORDER_CACHE_KEY_";
    private static final List<String> saleOrderExtList = Lists.newArrayList("ZORO","ZORA","ZRE5");
    //退货销售单类型 不预占库存
    private final static List<String> returnGoodsExtList = Lists.newArrayList("ZRE2","ZRE3");
    public static final String EXCHANGE= "exchange";
    private static final String EXCHANGE_ORDER_TYPE = "ZCH2";
    private static final Integer MAX_PAGE_SIZE = 1000;

    @Override
    @ProcessInvoker(remark = "MnSapIf018V2Service", errorCode = "OTS-02-007-00-16-999", printLog = true)
    public MnSapCommResponse externalSyncDeliveryOrder(MnSapIf018Request mnSapIf018Request) {
        log.info("mnSapIf018Request:{}", JSON.toJSONString(mnSapIf018Request));
        MnSapCommResponse response = new MnSapCommResponse();

        // Try to get from mogodb if null
        if (mnSapIf018Request == null) {
            mnSapIf018Request = IntegrateUtils.safeGetMessageObject(MnSapIf018Request.class);
        }

        response.setMessageId(mnSapIf018Request.getMessageHeader().getMessageId());
        response.setInterfacePath(mnSapIf018Request.getMessageHeader().getInterfacePath());

        AllocateOrderDeliveryRequest allocateOrderDeliveryRequest = new AllocateOrderDeliveryRequest();
        for (MnSapIf018SDO data : mnSapIf018Request.getData()) {
            //加锁 锁住交货单号
            String deliveryOrderId = SapAndCrmFieldDealUtils.generateIdField(data.getDeliveryOrderId());
            String lockKey = DELIVERY_ORDER_LOCK + deliveryOrderId;
            try(RedisLock lock = new RedisLock(BcOtsConstants.REDIS_CACHE_CODE(), lockKey,
                    5 * 60 * 1000,10 * 60 * 1000)){
                if (!lock.lock()){
                    List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
                    MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                    mnSapCommSDO.setMessage("获取分布式锁错误");
                    mnSapCommSDO.setStatus("E");
                    mnSapCommSDOS.add(mnSapCommSDO);
                    response.setData(mnSapCommSDOS);
                    //写入重试表
                    saveSapRetry(mnSapIf018Request,"获取分布式锁错误");
                    return response;
                }

            //2022.05.18 如果交货单删除时还找不到 那就要重试
            ConsignmentOrderLoadListRequest consignmentOrderLoadListRequest = new ConsignmentOrderLoadListRequest();
            consignmentOrderLoadListRequest.setOuterDeliveryOrderId(SapAndCrmFieldDealUtils.generateIdField(data.getDeliveryOrderId()));
            consignmentOrderLoadListRequest.setStatus(1);
            Result<List<ConsignmentOrder>> loadConsignmentOrderList = consignmentOrderService.loadConsignmentOrderList(consignmentOrderLoadListRequest);
            if (Objects.isNull(loadConsignmentOrderList) || CollectionUtils.isEmpty(loadConsignmentOrderList.getResult())){
                log.error("sapDelConsignmentOrderError:{}", JSON.toJSONString(mnSapIf018Request));
                List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
                MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                mnSapCommSDO.setMessage("交货单不存在");
                mnSapCommSDO.setStatus("E");
                mnSapCommSDOS.add(mnSapCommSDO);
                response.setData(mnSapCommSDOS);
                //写入重试表
                saveSapRetry(mnSapIf018Request,"交货单不存在");
                return response;
            }
            //需要判断交货单是否被冲销 而且这里先只判断销售单的
                ConsignmentOrder consignmentOrder = loadConsignmentOrderList.getResult().get(0);
//                //交货单需要处于删除状态
//                if (!Objects.equals(0,consignmentOrder.getStatus())){
//                    LOG.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrder:{}",JSON.toJSONString(SapAndCrmFieldDealUtils.generateIdField(data.getDeliveryOrderId())),JSON.toJSONString(consignmentOrder));
//                    throw new FacadeException("OTS-03-005-00-15-161");
//                }
                //判断一下
                String outerSalesOrderId = StringUtils.isNotBlank(consignmentOrder.getOuterSalesOrderId())?
                        consignmentOrder.getOuterSalesOrderId() : consignmentOrder.getOuterStoOrderId();
                //如果销售单存在查销售单
                if (StringUtils.isBlank(outerSalesOrderId)){
                    throw new FacadeException("OTS-03-005-00-15-162");
                }
                //交货单删除和销售单报文并发，增加唯一
                String saleOrderLockKey =SAP_SYNC + outerSalesOrderId;
                asyncSendMsgToKafka(outerSalesOrderId);
                try(SaleRedisLock saleLock = new SaleRedisLock(BcOtsConstants.REDIS_CACHE_CODE(), saleOrderLockKey,
                        2 * 60 * 1000,10 * 60 * 1000)){
                    if (!saleLock.lock()){
                        List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
                        MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                        mnSapCommSDO.setMessage("获取订单分布式锁错误");
                        mnSapCommSDO.setStatus("E");
                        mnSapCommSDOS.add(mnSapCommSDO);
                        response.setData(mnSapCommSDOS);
                        //写入重试表
                        saveSapRetry(mnSapIf018Request,"获取订单分布式锁错误");
                        return response;
                    }


                    LoadOrderListRequest loadOrderListRequest = new LoadOrderListRequest();
                    loadOrderListRequest.setOuterOrderId(outerSalesOrderId);
                    Result<List<Order>> listResult = orderService.loadOrderList(loadOrderListRequest);
                    //是销售单都存在
                    if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
                        List<Order> result = listResult.getResult();
                        Order order = result.get(0);
                        if(StringUtils.isNotBlank(order.getFulfillmentTypeCode())){
                            //非外仓履约
                            if(!isExternalWarehouseFulfillment(order.getFulfillmentTypeCode())){
                                boolean deleteDeliveryResult= deleteDelivery(consignmentOrder);
                                List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
                                MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                                if(deleteDeliveryResult){
                                    mnSapCommSDO.setMessage("成功");
                                    mnSapCommSDO.setStatus("S");
                                }else{
                                    mnSapCommSDO.setMessage("失败");
                                    mnSapCommSDO.setStatus("E");
                                }
                                mnSapCommSDOS.add(mnSapCommSDO);
                                response.setData(mnSapCommSDOS);
                                return response;
                            }
                        }
                        //如果是退货的直接返回 换货的只处理还货的交货单
                        if (!returnGoodsExtList.contains(order.getOrderType())){
                            Integer status = order.getStatus();

                            QueryWmsOrderByDeliveryOrderCodeRequest queryWmsOrderByDeliveryOrderCodeRequest =
                                    new QueryWmsOrderByDeliveryOrderCodeRequest(SapAndCrmFieldDealUtils.generateIdField(data.getDeliveryOrderId()));
                            Result<List<WmsOrder>> wmsOrderResult = crUnifiedInventoryService.queryWmsOrderByDeliveryOrderCode(queryWmsOrderByDeliveryOrderCodeRequest);
                            boolean flag = false;
                            //
                            if (wmsOrderResult != null && CollectionUtils.isNotEmpty(wmsOrderResult.getResult())){
                                boolean match = wmsOrderResult.getResult().stream().anyMatch(x -> Objects.equals(x.getOrderStatus(), 12));
                                flag = !match;
                            }
//                        if (!Objects.equals(status,OrderStatus.BEFORE_DELIVERY.getCode()) && flag){
//                        if (flag || !Objects.equals(status,OrderStatus.BEFORE_DELIVERY.getCode())){
                            if (flag){
                                log.error("sapDelConsignmentOrderError_status:{}",status);
                                log.error("sapDelConsignmentOrderError:{}", JSON.toJSONString(mnSapIf018Request));
                                List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
                                MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                                mnSapCommSDO.setMessage("未被冲销的交货单不能删除");
                                mnSapCommSDO.setStatus("E");
                                mnSapCommSDOS.add(mnSapCommSDO);
                                response.setData(mnSapCommSDOS);
                                //写入重试表
                                saveSapRetry(mnSapIf018Request,"未被冲销的交货单不能删除");
                                return response;
                            }
                        }
                    }
                    ConsignmentOrderWriteUpdateRequest request = new ConsignmentOrderWriteUpdateRequest();
                    request.setOuterDeliveryOrderId(SapAndCrmFieldDealUtils.generateIdField(data.getDeliveryOrderId()));
                    consignmentOrderWriteService.deleteBySapDeliveryOrder(request);
                    try {
                        //更改调拨单的交货数量
                        AllocateOrderCancelDeliveredRequest cancelDeliveredRequest = new AllocateOrderCancelDeliveredRequest();
                        cancelDeliveredRequest.setDeliveryOrderId(data.getDeliveryOrderId());
                        allocateOrderWriteService.cancelDelivered(cancelDeliveredRequest);
                    } catch (Exception e) {
                        log.error("MnSapIf018Service.externalSyncDeliveryOrder error", e);
                    }
                    occupyRelease(SapAndCrmFieldDealUtils.generateIdField(data.getDeliveryOrderId()));
                }catch (Throwable e){
                    log.error("MnSapIf018V2ServiceImpl_DelDeliveryOrderSaleLockError:{},exception:{}", JSON.toJSONString(mnSapIf018Request),e);
                    List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
                    MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                    mnSapCommSDO.setMessage(e.getMessage());
                    mnSapCommSDO.setStatus("E");
                    mnSapCommSDOS.add(mnSapCommSDO);
                    response.setData(mnSapCommSDOS);
                    //写入重试表
                    saveSapRetry(mnSapIf018Request,e.getMessage());
                    return response;
                }


            }catch (Throwable e){
                e.printStackTrace();
                log.error("MnSapIf018V2ServiceImpl_DelDeliveryOrderLockError:{},exception:{}", JSON.toJSONString(mnSapIf018Request),e);
                List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
                MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                mnSapCommSDO.setMessage(e.getMessage());
                mnSapCommSDO.setStatus("E");
                mnSapCommSDOS.add(mnSapCommSDO);
                response.setData(mnSapCommSDOS);
                //写入重试表
                saveSapRetry(mnSapIf018Request,e.getMessage());
                return response;
            }
        }


        List<MnSapCommSDO> mnSapCommSDOS = new ArrayList<>();
        MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
        mnSapCommSDO.setMessage("成功");
        mnSapCommSDO.setStatus("S");
        mnSapCommSDOS.add(mnSapCommSDO);
        response.setData(mnSapCommSDOS);
        return response;
    }

    /**
     * 发送mq消息，异步发送kafka消息通知应用端
     */
    private void asyncSendMsgToKafka(String outSourceOrderId){
        if (StringUtils.isBlank(outSourceOrderId)) {
            return;
        }

        LoadOrderListRequest pageQueryRequest = new LoadOrderListRequest();
        pageQueryRequest.setOuterOrderId(outSourceOrderId);
        Result<List<Order>> listResult= orderService.loadOrderList(pageQueryRequest);
        if (Objects.isNull(listResult) || CollectionUtils.isEmpty(listResult.getResult())) {
            return;
        }
        Order order = listResult.getResult().get(0);
        if (!JsonUtil.checkOrderCenterTag(order.getFeatures())) {
            // 非订单中心订单不发kafka消息
            return;
        }

        PushOrderInfoToMnSideRequestOrderInfo pushOrderInfo = new PushOrderInfoToMnSideRequestOrderInfo();
        pushOrderInfo.setSalesOrderNo(order.getOrderBizId());
        pushOrderInfo.setOrderStatus(SalesOrderPushStatusEnum.SUCCESS_UPDATE.getOrderStatusCode());

        CommonAsyncMessageResponse commonAsyncMessageResponse = new CommonAsyncMessageResponse();
        commonAsyncMessageResponse.setEventCode(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getValue());
        commonAsyncMessageResponse.setEventName(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getLabel());
        commonAsyncMessageResponse.setEventTime(String.valueOf(new Date().getTime()));
        commonAsyncMessageResponse.setFromSys(order.getFromSys());
        commonAsyncMessageResponse.setBusinessUnitCode(order.getBisUnitOutCode());
        commonAsyncMessageResponse.setData(Arrays.asList(pushOrderInfo));
        messageService.sendMessage("ORDER_STATUSCHANGE_PUSH_MESSAGE", "CR_SALEORDER_V2", "SaleOrderPushMn",
                JSONObject.toJSONString(commonAsyncMessageResponse));
        log.info("MnSapIf018V2Service#asynSendMsgToKafka commonAsyncMessageResponse: {}", commonAsyncMessageResponse);
    }

    public void saveSapRetry(MnSapIf018Request request,String code) {
        try {
            if (request == null || StringUtils.isBlank(code)) {
                return;
            }
            MnSapIf018SDO sdo = request.getData().get(0);
            SapRetrySaveRequest sapRetrySaveRequest = new SapRetrySaveRequest();
            String requestJson = JSON.toJSONString(request);
            sapRetrySaveRequest.setParam(requestJson);
            sapRetrySaveRequest.setMsg(code);
            sapRetrySaveRequest.setMessageId(request.getMessageHeader().getMessageId());
            //请求时间戳
//            sapRetrySaveRequest.setRequestTime(sdo.getExt());
            sapRetrySaveRequest.setApiCode(SapApiCode.SAP018.getValue());
            sapRetrySaveRequest.setOutKey(sdo.getDeliveryOrderId());
            sapRetrySaveRequest.setStatus(RetryStatus.FAIL.getValue());
            sapRetryWriteService.save(sapRetrySaveRequest);
        } catch (Throwable e) {
            log.error("sapRetrySaveError", e);
        }
    }

    //首先要判断是不是销售单
    private boolean occupyRelease(String outDeliveryOrderNo){
        OccupyReleaseRequest occupyReleaseRequest = new OccupyReleaseRequest();
        //判断此次018是否是销售单的
        ConsignmentOrderLoadListRequest consignmentOrderLoadListRequest = new ConsignmentOrderLoadListRequest();
        consignmentOrderLoadListRequest.setOuterDeliveryOrderId(outDeliveryOrderNo);
        Result<List<ConsignmentOrder>> loadConsignmentOrderList = consignmentOrderService.loadConsignmentOrderList(consignmentOrderLoadListRequest);
        //交货单需要存在
        if (loadConsignmentOrderList == null || CollectionUtils.isEmpty(loadConsignmentOrderList.getResult())){

            throw new FacadeException("OTS-03-005-00-15-160");
        }
        ConsignmentOrder consignmentOrder = loadConsignmentOrderList.getResult().get(0);
        //2023.11.08 如果是新疆销售组织的调拨单, 就不处理预占了
//        if (getFilterSaleOrgSet().contains(consignmentOrder.getSalesOrgId())){
//            return true;
//        }
        if (strategyQueryAbility.avoidDeliveryOrderOccupy(consignmentOrder.getSalesOrgId())){
            return true;
        }
        //交货单需要处于删除状态
        if (!Objects.equals(0,consignmentOrder.getStatus())){
            log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrder:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(consignmentOrder));
            throw new FacadeException("OTS-03-005-00-15-161");
        }
        //判断一下
        String outerSalesOrderId = StringUtils.isNotBlank(consignmentOrder.getOuterSalesOrderId())?
                consignmentOrder.getOuterSalesOrderId() : consignmentOrder.getOuterStoOrderId();
        //如果销售单存在查销售单
        if (StringUtils.isBlank(outerSalesOrderId)){
            throw new FacadeException("OTS-03-005-00-15-162");
        }
        LoadOrderListRequest loadOrderListRequest = new LoadOrderListRequest();
        loadOrderListRequest.setOuterOrderId(outerSalesOrderId);
        Result<List<Order>> orderListResult = orderService.loadOrderList(loadOrderListRequest);
        //2023.02.01 如果销售单被删除了 再从从order备份表查询数据 也查不到返回
        if (orderListResult == null || CollectionUtils.isEmpty(orderListResult.getResult())){
            OrderBackUpLoadListRequest orderBackUpLoadListRequest = new OrderBackUpLoadListRequest();
            orderBackUpLoadListRequest.setOuterOrderId(outerSalesOrderId);
            Result<List<OrderBackUp>> listResult = orderBackUpService.loadList(orderBackUpLoadListRequest);
            if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())){
                log.error("MnSapIf018V2ServiceImpl_order_is_deleted:{}",outDeliveryOrderNo);
                return true;
            }
            //类型转换一下
            orderListResult = JSON.parseObject(JSON.toJSONString(listResult),new TypeReference<Result<List<Order>>>(){
            });
        }
        //如果是销售单
        if (orderListResult != null && CollectionUtils.isNotEmpty(orderListResult.getResult())){
            List<Order> orderList = orderListResult.getResult();
            Order order = orderList.get(0);
            //如果是退货的直接返回 换货的只处理还货的交货单
            if (returnGoodsExtList.contains(order.getOrderType())){
                log.info("MnSapIf018V2ServiceImpl_occupyRelease_ReturnOrder:{}",JSON.toJSONString(order));
                return true;
            }

            //逻辑仓库id
            String wareHouseCode = order.getWareHouseCode();
            //获取仓库档案id
            //获取交货单明细
            ConsignmentOrderLineLoadListRequest consignmentOrderLineLoadListRequest = new ConsignmentOrderLineLoadListRequest();
            consignmentOrderLineLoadListRequest.setConsignmentOrderId(consignmentOrder.getId().toString());
            consignmentOrderLineLoadListRequest.setLimit(MAX_PAGE_SIZE);
            Result<List<ConsignmentOrderLine>> listResult = consignmentOrderLineService.loadConsignmentOrderLineList(consignmentOrderLineLoadListRequest);
            if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){

                //如果是换货的 退货行 需要删除
                if (EXCHANGE_ORDER_TYPE.equalsIgnoreCase(order.getOrderType())){
                    boolean match = listResult.getResult().stream().allMatch(x -> StringUtils.isNotBlank(x.getSoLineId()) && Integer.valueOf(x.getSoLineId().trim()) % 2 == 0);
                    if (!match){
                        log.info("MnSapIf018V2ServiceImpl_occupyRelease_Exchange_ReturnOrder:{}",JSON.toJSONString(order));
                        return true;
                    }
                }
                //获取 outSOLineId - quantity 理论上行不会重复
                Map<String, List<ConsignmentOrderLine>> lineMap = listResult.getResult().stream().collect(Collectors.groupingBy(ConsignmentOrderLine::getOuterSoLineId));
                List<InvOperateLine> invOperateLineList = Lists.newArrayList();
                lineMap.forEach((k,v)->{
                    InvOperateLine invOperateLine = new InvOperateLine();
                    if (CollectionUtils.isEmpty(v)){
                        //error
                        log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-163");
                    }
                    String scItemId = v.get(0).getScItemId();
                    if (StringUtils.isBlank(scItemId)){
                        //error
                        log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-164");
                    }
                    invOperateLine.setGoodsId(scItemId);
                    invOperateLine.setDeleted(true);
                    invOperateLine.setType("2");
                    invOperateLine.setOutOrderId(outDeliveryOrderNo);
//                    invOperateLine.setOutSubOrderId(outDeliveryOrderNo);
                    invOperateLine.setWarehouseAreaId(wareHouseCode);
                    //
                    WmsSDO wmsSDO = InfoUtil.getWmsSDO(wareHouseCode);
                    if (StringUtils.isBlank(wmsSDO.getWarehouseId())){
                        //error
                        log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-165");
                    }
                    invOperateLine.setWarehouseId(wmsSDO.getWarehouseId());
                    invOperateLine.setReferenceOrderId(order.getId().toString());
                    OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
                    orderLineLoadListRequest.setMainOrderId(order.getId().toString());
                    orderLineLoadListRequest.setOuterOrderLineId(k);
                    log.info("MnSapIf018V2ServiceImpl_occupyRelease_loadOrderLine_request:{}",JSON.toJSONString(orderLineLoadListRequest));
                    Result<List<OrderLine>> lineResult = orderLineService.loadOrderLineList(orderLineLoadListRequest);
                    //2023.02.01 如果订单明细查不到 也要去orderLine备份表再查一次
                    if (lineResult == null || CollectionUtils.isEmpty(lineResult.getResult())){
                        OrderLineBackUpLoadListRequest orderLineBackUpLoadListRequest = new OrderLineBackUpLoadListRequest();
                        orderLineBackUpLoadListRequest.setMainOrderId(order.getId().toString());
                        orderLineBackUpLoadListRequest.setOuterOrderLineId(k);
                        Result<List<OrderLineBackUp>> result = orderLineBackUpService.loadList(orderLineBackUpLoadListRequest);
                        if (result == null || CollectionUtils.isEmpty(result.getResult())){
                            //error
                            log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                            throw new FacadeException("OTS-03-005-00-15-166");
                        }
                        lineResult = JSON.parseObject(JSON.toJSONString(result),new TypeReference<Result<List<OrderLine>>>(){});
                    }
                    if (lineResult == null || CollectionUtils.isEmpty(lineResult.getResult())){
                        //error
                        log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-166");
                    }
                    OrderLine orderLine = lineResult.getResult().get(0);
                    invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                    //发现没有时间戳 用交货单号代替了  交货单号加上子单行号用来幂等
                    invOperateLine.setOutSubOrderId(outDeliveryOrderNo + "." + orderLine.getId().toString());

                    Long quantity = v.stream().mapToLong(x -> {
                        if (StringUtils.isBlank(x.getBasicQuantity())) {
                            return 0L;
                        }
                        BigDecimal bigDecimal = new BigDecimal(x.getBasicQuantity().trim());
                        return bigDecimal.movePointRight(3).longValue();
                    }).sum();
                    if (quantity <= 0 ){
                        //error
                        log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                        throw new FacadeException("OTS-03-005-00-15-167");
                    }
                    invOperateLine.setQuantity(quantity.toString());
                    invOperateLineList.add(invOperateLine);
                });
                if (CollectionUtils.isEmpty(invOperateLineList)){
                    //error
                    log.error("MnSapIf018V2ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(lineMap));
                    throw new FacadeException("OTS-03-005-00-15-168");
                }
                occupyReleaseRequest.setInvOperateLineList(invOperateLineList);
                log.info("MnSapIf018V2ServiceImpl_occupyRelease,request:{},occupyReleaseRequest:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(occupyReleaseRequest));
                Result<OccupyReleaseResponse> occupyReleaseResponseResult = crUnifiedInventoryService.occupyRelease(occupyReleaseRequest);
                log.info("MnSapIf018V2ServiceImpl_occupyRelease,result:{},occupyReleaseRequest:{},occupyReleaseResult:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(occupyReleaseRequest),JSON.toJSONString(occupyReleaseResponseResult));
                if (occupyReleaseResponseResult == null || !occupyReleaseResponseResult.isSuccess()){
                    //error
                    throw new FacadeException("OTS-03-005-00-15-169");
                }
            }
        }
        return true;
    }

    /**
     * 关闭交货单,大仓履约，就直接关闭交货单
     *  不等与外仓履约，外仓发-外仓收，排除
     * @param consignmentOrderParam
     * @return
     */
    private boolean deleteDelivery(ConsignmentOrder consignmentOrderParam){
        log.info("consignmentOrderParam:{}", JSON.toJSONString(consignmentOrderParam));
        ConsignmentOrderWriteUpdateRequest request = new ConsignmentOrderWriteUpdateRequest();
        request.setOuterDeliveryOrderId(RemoveZeroUtil.removeZeroPrefix(consignmentOrderParam.getOuterDeliveryOrderId()));
        Result<Boolean> booleanResult = consignmentOrderWriteService.deleteBySapDeliveryOrder(request);
        if(Objects.isNull(booleanResult)){
            return false;
        }
        return booleanResult.getResult();
//        QueryConsignmentOrderLineRequest queryConsignmentOrderLineRequest= new QueryConsignmentOrderLineRequest();
//            queryConsignmentOrderLineRequest.setConsignmentOrderId(RemoveZeroUtil.removeZeroPrefix(consignmentOrderParam.getOuterDeliveryOrderId()));
//            Result<List<ConsignmentOrderLine>>  consignmentOrderLineResult = consignmentOrderLineService.queryConsignmentOrderLine(queryConsignmentOrderLineRequest);
//            log.info("MnSapIf018V2ServiceImpl_queryConsignmentOrderLine,consignmentOrderLineResult:{}",JSON.toJSONString(consignmentOrderLineResult));
//            if(consignmentOrderLineResult.isSuccess() && CollectionUtils.isNotEmpty(consignmentOrderLineResult.getResult())){
//                consignmentOrderLineResult.getResult().forEach(consignmentOrderLine -> {
//                    ConsignmentOrderLine consignmentOrderLine1 = new ConsignmentOrderLine();
//                    consignmentOrderLine1.setId(consignmentOrderLine.getId());
//                    consignmentOrderLine1.setStatus(0);
//                    UpdateConsignmentOrderLineResponse updateConsignmentOrderLine = consignmentOrderLineService.updateConsignmentOrderLine(consignmentOrderLine1);
//                    if(updateConsignmentOrderLine.getCount()<1){
//                        log.error("MnSapIf018V2ServiceImpl_updateConsignmentOrderLine_Error,consignmentOrderLine1:{}",JSON.toJSONString(consignmentOrderLine1));
//                        throw new RuntimeException("删除交货单行失败");
//                    }
//                });
//            }
//        ConsignmentOrder consignmentOrder = new ConsignmentOrder();
//        consignmentOrder.setId(consignmentOrderParam.getId());
//        consignmentOrder.setStatus(0);
//        UpdateConsignmentOrderResponse updateConsignmentOrder =consignmentOrderService.updateConsignmentOrder(consignmentOrder);
//            if(updateConsignmentOrder.getCount()<1){
//                log.error("MnSapIf018V2ServiceImpl_updateConsignmentOrder_Error,consignmentOrder:{}",JSON.toJSONString(consignmentOrder));
//                throw new RuntimeException("删除交货单失败");
//            }
//        String outerDeliverOrderId = RemoveZeroUtil.removeZeroPrefix(consignmentOrderParam.getOuterDeliveryOrderId());
//        ConsignmentOrderSDO consignmentOrderSDO = new ConsignmentOrderSDO();
//        consignmentOrderSDO.setOuterDeliveryOrderId(outerDeliverOrderId);
//        messageService.sendMessage("consignment_order_message", "CR_CONSIGNMENT_V2", "updateOrderDeliveryQty", outerDeliverOrderId, JSON.toJSONString(consignmentOrderSDO));

//        return true;
    }

    /**
     * （销售订单）履约方式是否是外仓履约
     * @return
     */
    boolean isExternalWarehouseFulfillment(String fulfillmentTypeCode) {
        if (!Objects.equals(fulfillmentTypeCode, GroupConstants.FB_EXTERNAL_WAREHOUSE_FULFILLMENT) && !Objects.equals(fulfillmentTypeCode, GroupConstants.Bb_EXTERNAL_WAREHOUSE_FULFILLMENT)) {
            return false;
        }
        return true;
    }
}
